package org.qpcr.community.project.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult;
import org.hswebframework.web.crud.service.GenericReactiveCrudService;
import org.hswebframework.web.exception.BusinessException;
import org.qpcr.community.project.enums.DataAnalysisDashboardXField;
import org.qpcr.community.project.enums.InterpretationOperator;
import org.qpcr.community.project.model.entity.DataAnalysisDashboardChartsEntity;
import org.qpcr.community.project.request.DataAnalysisDashboardChartsSaveRequest;
import org.qpcr.community.project.request.DataAnalysisDashboardQuery;
import org.qpcr.community.project.request.DataAnalysisRequest;
import org.qpcr.community.project.response.*;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.qpcr.community.project.model.entity.DataAnalysisDashboardChartsXGroupEntity;
import org.qpcr.community.project.model.entity.DataAnalysisDashboardChartsFilterConditionEntity;
import org.qpcr.community.project.model.entity.DataGroupExperimentalRecordsRelateEntity;
import org.qpcr.community.project.model.entity.DataAnalysisExperimentalRecordsEntity;

@Service
@Slf4j
@RequiredArgsConstructor
public class DataAnalysisDashboardChartsService extends GenericReactiveCrudService<DataAnalysisDashboardChartsEntity, String> {
    @Resource
    private DataAnalysisDashboardChartsXGroupService dataAnalysisDashboardChartsXGroupService;
    @Resource
    private DataAnalysisDashboardChartsFilterConditionService dataAnalysisDashboardChartsFilterConditionService;
    @Resource
    private DataGroupExperimentalRecordsRelateService  dataGroupExperimentalRecordsRelateService;
    @Resource
    private DataAnalysisExperimentalRecordsService dataAnalysisExperimentalRecordsService;
    @Resource
    private DataGroupTypeService dataGroupTypeService;

    public Mono<Integer> deleteAllById(String id) {
        // 先删除XGroup和FilterCondition，再删除主表
        Mono<Void> deleteXGroup = dataAnalysisDashboardChartsXGroupService.createDelete()
            .is(DataAnalysisDashboardChartsXGroupEntity::getChartId, id)
            .execute()
            .then();
        Mono<Void> deleteFilter = dataAnalysisDashboardChartsFilterConditionService.createDelete()
            .is(DataAnalysisDashboardChartsFilterConditionEntity::getChartId, id)
            .execute()
            .then();
        Mono<Integer> deleteChart = createDelete()
            .is(DataAnalysisDashboardChartsEntity::getId, id)
            .execute();
        return Mono.when(deleteXGroup, deleteFilter).then(deleteChart);
    }

    public Mono<Integer> cloneChart(String id) {
        // 1. 查询原图表
        return super.createQuery()
            .where(DataAnalysisDashboardChartsEntity::getId, id)
            .fetchOne()
            .flatMap(originChart -> {
                if (originChart == null) return Mono.just(0);
                // 2. 查询XGroup和FilterCondition
                Mono<List<DataAnalysisDashboardChartsXGroupEntity>> xGroupsMono = dataAnalysisDashboardChartsXGroupService.createQuery()
                    .where(DataAnalysisDashboardChartsXGroupEntity::getChartId, id)
                    .fetch()
                    .collectList();
                Mono<List<DataAnalysisDashboardChartsFilterConditionEntity>> filterMono = dataAnalysisDashboardChartsFilterConditionService.createQuery()
                    .where(DataAnalysisDashboardChartsFilterConditionEntity::getChartId, id)
                    .fetch()
                    .collectList();
                return Mono.zip(xGroupsMono, filterMono)
                    .flatMap(tuple -> {
                        List<DataAnalysisDashboardChartsXGroupEntity> xGroups = tuple.getT1();
                        List<DataAnalysisDashboardChartsFilterConditionEntity> filters = tuple.getT2();
                        // 3. 复制对象，生成新ID
                        String newId = String.valueOf(System.currentTimeMillis());
                        DataAnalysisDashboardChartsEntity newChart = new DataAnalysisDashboardChartsEntity();
                        org.springframework.beans.BeanUtils.copyProperties(originChart, newChart);
                        newChart.setId(newId);
                        String randomStr = java.util.UUID.randomUUID().toString().replace("-", "").substring(0, 6);
                        newChart.setChartName(originChart.getChartName() + "_副本" + randomStr);
                        // 复制XGroup
                        List<DataAnalysisDashboardChartsXGroupEntity> newXGroups = new java.util.ArrayList<>();
                        if (xGroups != null) {
                            for (DataAnalysisDashboardChartsXGroupEntity x : xGroups) {
                                DataAnalysisDashboardChartsXGroupEntity nx = new DataAnalysisDashboardChartsXGroupEntity();
                                org.springframework.beans.BeanUtils.copyProperties(x, nx);
                                nx.setId(null);
                                nx.setChartId(newId);
                                newXGroups.add(nx);
                            }
                        }
                        // 复制FilterCondition
                        List<DataAnalysisDashboardChartsFilterConditionEntity> newFilters = new java.util.ArrayList<>();
                        if (filters != null) {
                            for (DataAnalysisDashboardChartsFilterConditionEntity f : filters) {
                                DataAnalysisDashboardChartsFilterConditionEntity nf = new DataAnalysisDashboardChartsFilterConditionEntity();
                                org.springframework.beans.BeanUtils.copyProperties(f, nf);
                                nf.setId(null);
                                nf.setChartId(newId);
                                newFilters.add(nf);
                            }
                        }
                        // 4. 插入新图表、新XGroup、新FilterCondition
                        return super.insert(newChart)
                            .then(dataAnalysisDashboardChartsXGroupService.saveBatch(newXGroups))
                            .then(dataAnalysisDashboardChartsFilterConditionService.saveBatch(newFilters))
                            .thenReturn(1);
                    });
            });
    }

    public Mono<Integer> rename(DataAnalysisDashboardChartsSaveRequest request) {
        DataAnalysisDashboardChartsEntity chart = request.getChart();
        return createUpdate()
            .set(DataAnalysisDashboardChartsEntity::getChartName, chart.getChartName())
            .is(DataAnalysisDashboardChartsEntity::getId, chart.getId())
            .execute();
    }


    public Mono<Void> saveAll(DataAnalysisDashboardChartsSaveRequest request) {
        DataAnalysisDashboardChartsEntity chart = request.getChart();
        // 如果id为空，手动生成（建议用雪花算法或UUID）
        if (chart.getId() == null || chart.getId().trim().isEmpty()) {
            // 这里建议替换为你项目的雪花算法ID生成器
            chart.setId(String.valueOf(System.currentTimeMillis()));
        }
        String chartId = chart.getId();

        return super.save(Mono.just(chart))
            .then(
                // 删除
                dataAnalysisDashboardChartsXGroupService.createDelete()
                    .is(DataAnalysisDashboardChartsXGroupEntity::getChartId, chartId)
                    .execute()
                    .then(
                        dataAnalysisDashboardChartsFilterConditionService.createDelete()
                            .is(DataAnalysisDashboardChartsFilterConditionEntity::getChartId, chartId)
                            .execute()
                    )
                    // 插入
                    .then(Mono.defer(() -> {
                        List<DataAnalysisDashboardChartsXGroupEntity> xGroups = request.getHorizontalAxisGroups();
                        if (xGroups != null) xGroups.forEach(x -> x.setChartId(chartId));
                        List<DataAnalysisDashboardChartsFilterConditionEntity> filterConditions = request.getFilterConditions();
                        if (filterConditions != null) filterConditions.forEach(f -> f.setChartId(chartId));
                        Mono<Void> insertXGroupMono = dataAnalysisDashboardChartsXGroupService.saveBatch(xGroups);
                        Mono<Void> insertFilterConditionMono = dataAnalysisDashboardChartsFilterConditionService.saveBatch(filterConditions);
                        return insertXGroupMono.then(insertFilterConditionMono);
                    }))
            );
    }

    public List<DataAnalysisDashboardChartsEntity> listByGroupId(String groupId) {
        return createQuery()
            .is(DataAnalysisDashboardChartsEntity::getGroupId, groupId)
            .fetch()
            .collectList()
            .block();
    }

    public List<DataAnalysisDashboardChartsResponse> listByGroupIdSync(DataAnalysisDashboardQuery query) {
        List<DataAnalysisDashboardChartsResponse> responses = new ArrayList<>();
        List<DataAnalysisDashboardChartsEntity> charts = this.listByGroupId(query.getGroupId());

        if (charts != null &&  !charts.isEmpty()) {
            //遍历charts生成responses
            for (DataAnalysisDashboardChartsEntity chart : charts) {
                DataAnalysisDashboardChartsResponse resp = new DataAnalysisDashboardChartsResponse();
                resp.setGroupId(chart.getGroupId());
                resp.setChartId(chart.getId());
                resp.setChartName(chart.getChartName());
                resp.setChartType(chart.getChartType());
                resp.setChartData(null);
                responses.add(resp);
            }
        }

        if (null == query.getGroupTypeIds() || query.getGroupTypeIds().isEmpty()){
            return responses;
        }
        //查询实验数据
        List<String> recordIds = dataGroupExperimentalRecordsRelateService.listRecordIdsByGroupTypeIdsSync(query.getGroupTypeIds());

        List<DataAnalysisExperimentalRecordsEntity> experimentalRecords = new ArrayList<>();
        if (recordIds != null && !recordIds.isEmpty()) {
            List<DataAnalysisExperimentalRecordsEntity> selectRecords = dataAnalysisExperimentalRecordsService.listByIdsSync(recordIds);
            if (null != selectRecords && !selectRecords.isEmpty()){
                experimentalRecords.addAll(selectRecords);
            }
        }


        if (query.getGroupTypeIds().contains("other-data")) {
            List<String> allBindRecordIdsSync = dataGroupExperimentalRecordsRelateService.findAllBindRecordIdsSync(query.getGroupId());
            List<DataAnalysisExperimentalRecordsEntity> unBindRecords = dataAnalysisExperimentalRecordsService.listUnBindDataSync(query.getGroupId(), allBindRecordIdsSync);
            if (null != unBindRecords && !unBindRecords.isEmpty()){
                experimentalRecords.addAll(unBindRecords);
            }
        }

        if (null == experimentalRecords || experimentalRecords.isEmpty()){
            return responses;
        }

        Map<String, List<DataAnalysisDashboardChartsFilterConditionEntity>> filterConditions = dataAnalysisDashboardChartsFilterConditionService.getByGroupIdSync(query.getGroupId());

        Map<String, List<DataAnalysisDashboardChartsXGroupEntity>> xGroupMap = dataAnalysisDashboardChartsXGroupService.listMapByGroupId(query.getGroupId());

        for (DataAnalysisDashboardChartsResponse response : responses) {
            List<DataAnalysisDashboardChartsFilterConditionEntity> conditions = filterConditions.get(response.getChartId());
            List<DataAnalysisExperimentalRecordsEntity> currentRecords = new ArrayList<>();
            if (null != conditions && !conditions.isEmpty()){
                currentRecords = experimentalRecords.stream().filter(e -> {
                    DataAnalysisDashboardChartsFilterConditionEntity condition = conditions.get(0);
                    DataAnalysisDashboardXField byField = DataAnalysisDashboardXField.getByField(condition.getField());
                    Object apply = byField.getApply().apply(e);
                    String dataType = byField.getDataType();
                    InterpretationOperator operator = InterpretationOperator.fromName(condition.getOperator());

                    switch (operator) {
                        case EQUAL:
                            return apply.equals(condition.getValue1());
                        case LESS_THAN:
                            return Double.parseDouble(apply.toString()) < Double.parseDouble(condition.getValue1());
                        case LESS_THAN_OR_EQUAL:
                            return Double.parseDouble(apply.toString()) <= Double.parseDouble(condition.getValue1());
                        case GREATER_THAN:
                            return Double.parseDouble(apply.toString()) > Double.parseDouble(condition.getValue1());
                        case GREATER_THAN_OR_EQUAL:
                            return Double.parseDouble(apply.toString()) >= Double.parseDouble(condition.getValue1());
                        case BETWEEN:
                            return Double.parseDouble(apply.toString()) >= Double.parseDouble(condition.getValue1())
                                && Double.parseDouble(apply.toString()) <= Double.parseDouble(condition.getValue1());
                        default:
                            return apply.equals(condition.getValue1());
                    }
                }).collect(Collectors.toList());
            }else {
                currentRecords = experimentalRecords;
            }

            List<DataAnalysisDashboardChartsXGroupEntity> xGroups = xGroupMap.get(response.getChartId());
            if (null != xGroups && !xGroups.isEmpty()){
                List<String> legends = new ArrayList<>();
                Set<String> categoriesSet = new java.util.LinkedHashSet<>(); // 保证顺序
                List<DataAnalysisChartSeriesData> seriesList = new ArrayList<>();

                if (xGroups != null && !xGroups.isEmpty()){
                    DataAnalysisResultResponse dataAnalysisResultResponse = new  DataAnalysisResultResponse();
                    if (xGroups.get(0).getHorizontalAxisField().equals(DataAnalysisDashboardXField.YIN_YANG_TCM.getField())){
                        DataAnalysisRequest dataAnalysisRequest = new DataAnalysisRequest();
                        dataAnalysisRequest.setGroupId(query.getGroupId());
                        dataAnalysisRequest.setGroupTypeIds(query.getGroupTypeIds());
                        dataAnalysisResultResponse = dataGroupTypeService.analysisSync(dataAnalysisRequest);
                    }

                    for (DataAnalysisDashboardChartsXGroupEntity xGroup : xGroups) {
                        String legend = xGroup.getName();
                        legends.add(legend);
                        DataAnalysisChartSeriesData series = new DataAnalysisChartSeriesData();
                        series.setName(legend);
                        List<DataAnalysisChartDataPoint> points = new ArrayList<>();

                        DataAnalysisDashboardXField byField = DataAnalysisDashboardXField.getByField(xGroup.getHorizontalAxisField());
                        if (byField == null) continue;
                        if (byField == DataAnalysisDashboardXField.RECEIVE_TIME) {
                            int intervalDays = 1;
                            try { intervalDays = Integer.parseInt(xGroup.getValue1()); } catch (Exception e) {}
                            if (currentRecords == null || currentRecords.isEmpty()) continue;
                            long minTime = currentRecords.stream().mapToLong(DataAnalysisExperimentalRecordsEntity::getReceiveTime).min().orElse(0L);
                            java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
                            long intervalMillis = intervalDays * 24L * 60 * 60 * 1000;
                            java.util.Map<String, Integer> dateCountMap = new java.util.HashMap<>();
                            for (DataAnalysisExperimentalRecordsEntity rec : currentRecords) {
                                long diff = rec.getReceiveTime() - minTime;
                                long bucket = diff / intervalMillis;
                                long bucketStart = minTime + bucket * intervalMillis;
                                String dateStr = sdf.format(new java.util.Date(bucketStart));
                                dateCountMap.put(dateStr, dateCountMap.getOrDefault(dateStr, 0) + 1);
                            }
                            for (String date : dateCountMap.keySet()) {
                                categoriesSet.add(date);
                                DataAnalysisChartDataPoint p = new DataAnalysisChartDataPoint();
                                p.setCategory(date);
                                p.setValue(dateCountMap.get(date));
                                points.add(p);
                            }
                            series.setData(points);
                            seriesList.add(series);
                            continue;
                        }
                        if (byField.isYinYangTcm()){
                            DataAnalysisChartDataPoint point = new DataAnalysisChartDataPoint();
                            point.setCategory(legend);
                            if (xGroup.getValue1().equals("NEGATIVE")){
                                point.setValue(dataAnalysisResultResponse.getNegativeCount());
                            }
                            if (xGroup.getValue1().equals("POSITIVE")){
                                point.setValue(dataAnalysisResultResponse.getPositiveCount());
                            }
                            categoriesSet.add(legend);
                            points.add(point);
                            series.setData(points);
                            seriesList.add(series);
                            continue;
                        }
                        // collect 已经是当前xGroup下的数据
                        List<DataAnalysisExperimentalRecordsEntity> collect = currentRecords.stream().filter(c -> {
                            Object apply = byField.getApply().apply(c);
                            if (apply == null) throw  new BusinessException("您选择的数据中有`" + byField.getName() + "` 数据存在异常、请仔细核对数据的有效性");
                            InterpretationOperator operator = InterpretationOperator.fromName(xGroup.getOperator());
                            switch (operator) {
                                case EQUAL:
                                    if (apply instanceof Double) {
                                        return apply.equals(Double.parseDouble(xGroup.getValue1()));
                                    }
                                    return apply.equals(xGroup.getValue1());
                                case LESS_THAN:
                                    return Double.parseDouble(apply.toString()) < Double.parseDouble(xGroup.getValue1());
                                case LESS_THAN_OR_EQUAL:
                                    return Double.parseDouble(apply.toString()) <= Double.parseDouble(xGroup.getValue1());
                                case GREATER_THAN:
                                    return Double.parseDouble(apply.toString()) > Double.parseDouble(xGroup.getValue1());
                                case GREATER_THAN_OR_EQUAL:
                                    return Double.parseDouble(apply.toString()) >= Double.parseDouble(xGroup.getValue1());
                                case BETWEEN:
                                    return Double.parseDouble(apply.toString()) >= Double.parseDouble(xGroup.getValue1())
                                        && Double.parseDouble(apply.toString()) <= Double.parseDouble(xGroup.getValue2());
                                default:
                                    return apply.equals(xGroup.getValue1());
                            }
                        }).collect(Collectors.toList());
                        DataAnalysisChartDataPoint point = new DataAnalysisChartDataPoint();
                        point.setCategory(legend);
                        point.setValue(collect == null ? 0 : collect.size());
                        categoriesSet.add(legend);
                        points.add(point);
                        series.setData(points);
                        seriesList.add(series);
                    }
                    // 新增“其他”数据项逻辑
                    int groupedCount = seriesList.stream()
                        .flatMap(s -> s.getData().stream())
                        .mapToInt(p -> p.getValue() == null ? 0 : p.getValue().intValue())
                        .sum();
                    int otherCount = currentRecords.size() - groupedCount;
                    String otherLegend = "其他";
                    // 判断是否为检测时间+折线/柱状图
                    boolean isReceiveTime = xGroups != null && !xGroups.isEmpty() &&
                        DataAnalysisDashboardXField.RECEIVE_TIME.getField().equals(xGroups.get(0).getHorizontalAxisField());
                    boolean isLineOrBar = "line".equalsIgnoreCase(response.getChartType()) || "bar".equalsIgnoreCase(response.getChartType());
                    if (isReceiveTime && isLineOrBar) {
                        // 对 categoriesSet 进行时间排序（由远及近）
                        java.util.List<String> sortedCategories = new java.util.ArrayList<>(categoriesSet);
                        java.util.Collections.sort(sortedCategories);
                        // 作为一个新的时间点加入
                        String otherCategory = "其他";
                        sortedCategories.add(otherCategory);
                        // 更新 seriesList 中所有 series 的数据点顺序
                        for (DataAnalysisChartSeriesData s : seriesList) {
                            java.util.Map<String, DataAnalysisChartDataPoint> pointMap = new java.util.HashMap<>();
                            for (DataAnalysisChartDataPoint p : s.getData()) {
                                pointMap.put(p.getCategory(), p);
                            }
                            java.util.List<DataAnalysisChartDataPoint> newPoints = new java.util.ArrayList<>();
                            for (String cat : sortedCategories) {
                                if (pointMap.containsKey(cat)) {
                                    newPoints.add(pointMap.get(cat));
                                } else {
                                    DataAnalysisChartDataPoint emptyPoint = new DataAnalysisChartDataPoint();
                                    emptyPoint.setCategory(cat);
                                    emptyPoint.setValue(0);
                                    newPoints.add(emptyPoint);
                                }
                            }
                            s.setData(newPoints);
                        }
                        categoriesSet.clear();
                        categoriesSet.addAll(sortedCategories);
                        DataAnalysisChartDataPoint otherPoint = new DataAnalysisChartDataPoint();
                        otherPoint.setCategory(otherCategory);
                        otherPoint.setValue(otherCount < 0 ? 0 : otherCount);
                        // 只在第一个series上加“其他”点，或新建一个series
                        if (!seriesList.isEmpty()) {
                            // 已在排序时处理
                        } else {
                            DataAnalysisChartSeriesData otherSeries = new DataAnalysisChartSeriesData();
                            otherSeries.setName(legends.isEmpty() ? otherLegend : legends.get(0));
                            otherSeries.setData(java.util.Collections.singletonList(otherPoint));
                            seriesList.add(otherSeries);
                        }
                    } else {
                        // 其它情况，作为一个新的legend加入
                        legends.add(otherLegend);
                        categoriesSet.add(otherLegend);
                        DataAnalysisChartDataPoint otherPoint = new DataAnalysisChartDataPoint();
                        otherPoint.setCategory(otherLegend);
                        otherPoint.setValue(otherCount < 0 ? 0 : otherCount);
                        DataAnalysisChartSeriesData otherSeries = new DataAnalysisChartSeriesData();
                        otherSeries.setName(otherLegend);
                        otherSeries.setData(java.util.Collections.singletonList(otherPoint));
                        seriesList.add(otherSeries);
                    }
                    DataAnalysisChartData chartData = new DataAnalysisChartData();
                    chartData.setLegend(legends);
                    chartData.setCategories(new ArrayList<>(categoriesSet));
                    chartData.setSeries(seriesList);
                    response.setChartData(chartData);
                }
            }


        }

        return responses;
    }



    public Mono<List<DataAnalysisDashboardChartsResponse>> listByGroupId(DataAnalysisDashboardQuery query) {
        List<String> groupTypeIds = query.getGroupTypeIds();
        String groupId = query.getGroupId();

        Mono<List<DataAnalysisExperimentalRecordsEntity>> experimentalDataMono;
        if (groupTypeIds != null && !groupTypeIds.isEmpty()) {
            // 1. 查找实验数据
            experimentalDataMono = dataGroupExperimentalRecordsRelateService.listByGroupIds(groupTypeIds)
                .flatMap(relateEntities -> {
                    if (relateEntities == null || relateEntities.isEmpty()) {
                        return Mono.just(new java.util.ArrayList<DataAnalysisExperimentalRecordsEntity>());
                    }
                    List<String> recordIds = relateEntities.stream()
                        .map(DataGroupExperimentalRecordsRelateEntity::getRecordId)
                        .collect(java.util.stream.Collectors.toList());
                    return dataAnalysisExperimentalRecordsService.listByIds(recordIds);
                });
        } else {
            experimentalDataMono = Mono.just(new java.util.ArrayList<DataAnalysisExperimentalRecordsEntity>());
        }

        // 2. 查询全部图表配置
        Mono<List<DataAnalysisDashboardChartsEntity>> chartsMono = super.createQuery()
            .where(DataAnalysisDashboardChartsEntity::getGroupId, groupId)
            .fetch()
            .collectList();

        return Mono.zip(chartsMono, experimentalDataMono)
            .flatMap(tuple -> {
                List<DataAnalysisDashboardChartsEntity> charts = tuple.getT1();
                List<DataAnalysisExperimentalRecordsEntity> experimentalData = tuple.getT2();
                // 3. 如果实验数据为空，直接返回图表配置
                if (experimentalData == null || experimentalData.isEmpty()) {
                    List<DataAnalysisDashboardChartsResponse> responses = charts.stream().map(chart -> {
                        DataAnalysisDashboardChartsResponse resp = new DataAnalysisDashboardChartsResponse();
                        resp.setGroupId(chart.getGroupId());
                        resp.setChartId(chart.getId());
                        resp.setChartName(chart.getChartName());
                        resp.setChartType(chart.getChartType());
                        resp.setChartData(null);
                        return resp;
                    }).collect(java.util.stream.Collectors.toList());
                    return Mono.just(responses);
                }
                // 4. 有实验数据，遍历每个图表配置，组装chartData
                return Flux.fromIterable(charts)
                    .flatMap(chart -> {
                        DataAnalysisDashboardChartsResponse resp = new DataAnalysisDashboardChartsResponse();
                        resp.setGroupId(chart.getGroupId());
                        resp.setChartId(chart.getId());
                        resp.setChartName(chart.getChartName());
                        resp.setChartType(chart.getChartType());


                        // 1.查询FilterCondition配置根据条件过滤实验数据如果filterCondition为空则不进行过滤
                        // 2.查询XGroup配置根据配置组装chartData
                        // 3.返回chartData
                        return dataAnalysisDashboardChartsFilterConditionService.createQuery()
                            .where(DataAnalysisDashboardChartsFilterConditionEntity::getChartId, chart.getId())
                            .fetch()
                            .collectList()
                            .flatMap(filterConditions ->
                                dataAnalysisDashboardChartsXGroupService.createQuery()
                                    .where(DataAnalysisDashboardChartsXGroupEntity::getChartId, chart.getId())
                                    .fetch()
                                    .collectList()
                                    .map(xGroups -> {
                                        // 1. 过滤实验数据
                                        List<DataAnalysisExperimentalRecordsEntity> filteredData = experimentalData;
                                        if (filterConditions != null && !filterConditions.isEmpty()) {

                                            for (DataAnalysisDashboardChartsFilterConditionEntity filter : filterConditions) {
                                                String field = filter.getField();
                                                String operator = filter.getOperator();
                                                String value1 = filter.getValue1();
                                                String value2 = filter.getValue2();
                                                filteredData = filteredData.stream().filter(record -> {
                                                    // 使用DataAnalysisDashboardXField安全获取apply方法
                                                    Function<DataAnalysisExperimentalRecordsEntity, Object> fieldGetter = DataAnalysisDashboardXField.getApplyField(field);
                                                    if (fieldGetter == null) return false;
                                                    Object fieldValue = fieldGetter.apply(record);
                                                    if (fieldValue == null) return false;
                                                    try {
                                                        InterpretationOperator op = InterpretationOperator.fromName(operator);
                                                        double fv = Double.parseDouble(fieldValue.toString());
                                                        double v1 = value1 == null ? 0 : Double.parseDouble(value1);
                                                        double v2 = value2 == null ? 0 : Double.parseDouble(value2);
                                                        switch (op) {
                                                            case EQUAL:
                                                                return fv == v1;
                                                            case NOT_EQUAL:
                                                                return fv != v1;
                                                            case GREATER_THAN:
                                                                return fv > v1;
                                                            case LESS_THAN:
                                                                return fv < v1;
                                                            case GREATER_THAN_OR_EQUAL:
                                                                return fv >= v1;
                                                            case LESS_THAN_OR_EQUAL:
                                                                return fv <= v1;
                                                            case BETWEEN:
                                                                return fv >= v1 && fv <= v2;
                                                            case NOT_BETWEEN:
                                                                return fv < v1 || fv > v2;
                                                            default:
                                                                return true;
                                                        }
                                                    } catch (Exception e) {
                                                        // 兜底：如果解析失败则不过滤
                                                        return true;
                                                    }
                                                }).collect(Collectors.toList());
                                            }
                                        }

                                        // 2. 组装chartData
                                        DataAnalysisChartData chartData = new DataAnalysisChartData();
                                        String xField = chart.getHorizontalAxisField();
                                        Function<DataAnalysisExperimentalRecordsEntity, Object> xFieldGetter = DataAnalysisDashboardXField.getApplyField(xField);
                                        if (xFieldGetter == null) return resp;
                                        List<String> legends = new ArrayList<>();
                                        List<String> categories = new ArrayList<>();
                                        List<DataAnalysisChartSeriesData> seriesList = new ArrayList<>();

                                        for (DataAnalysisDashboardChartsXGroupEntity xGroup : xGroups) {
                                            String legend = xGroup.getName();
                                            legends.add(legend);

                                            // 1. 获取分组字段及条件
                                            String groupField = xGroup.getHorizontalAxisField();
                                            String groupOperator = xGroup.getOperator();
                                            String groupValue1 = xGroup.getValue1();
                                            String groupValue2 = xGroup.getValue2();
                                            Function<DataAnalysisExperimentalRecordsEntity, Object> groupFieldGetter = DataAnalysisDashboardXField.getApplyField(groupField);
                                            if (groupFieldGetter == null) continue;

                                            // 2. 先按XGroup条件过滤
                                            List<DataAnalysisExperimentalRecordsEntity> groupFiltered = filteredData.stream().filter(record -> {
                                                Object fieldValue = groupFieldGetter.apply(record);
                                                if (fieldValue == null) return false;
                                                try {
                                                    InterpretationOperator op = InterpretationOperator.fromName(groupOperator);
                                                    double fv = Double.parseDouble(fieldValue.toString());
                                                    double v1 = groupValue1 == null ? 0 : Double.parseDouble(groupValue1);
                                                    double v2 = groupValue2 == null ? 0 : Double.parseDouble(groupValue2);
                                                    switch (op) {
                                                        case EQUAL:
                                                            return fv == v1;
                                                        case NOT_EQUAL:
                                                            return fv != v1;
                                                        case GREATER_THAN:
                                                            return fv > v1;
                                                        case LESS_THAN:
                                                            return fv < v1;
                                                        case GREATER_THAN_OR_EQUAL:
                                                            return fv >= v1;
                                                        case LESS_THAN_OR_EQUAL:
                                                            return fv <= v1;
                                                        case BETWEEN:
                                                            return fv >= v1 && fv <= v2;
                                                        case NOT_BETWEEN:
                                                            return fv < v1 || fv > v2;
                                                        default:
                                                            return true;
                                                    }
                                                } catch (Exception e) {
                                                    return true;
                                                }
                                            }).collect(Collectors.toList());

                                            // 3. 再按分组字段分组
                                            Map<Object, List<DataAnalysisExperimentalRecordsEntity>> groupMap =
                                                groupFiltered.stream().collect(Collectors.groupingBy(groupFieldGetter));
                                            List<DataAnalysisChartDataPoint> points = new ArrayList<>();
                                            for (Object category : groupMap.keySet()) {
                                                categories.add(category == null ? "" : category.toString());
                                                List<DataAnalysisExperimentalRecordsEntity> groupRecords = groupMap.get(category);
                                                DataAnalysisChartDataPoint point = new DataAnalysisChartDataPoint();
                                                point.setCategory(category == null ? "" : category.toString());
                                                point.setValue(groupRecords == null ? 0 : groupRecords.size());
                                                points.add(point);
                                            }
                                            DataAnalysisChartSeriesData series = new DataAnalysisChartSeriesData();
                                            series.setName(legend);
                                            series.setData(points);
                                            seriesList.add(series);
                                        }
                                        chartData.setLegend(legends);
                                        chartData.setCategories(categories.stream().distinct().collect(Collectors.toList()));
                                        chartData.setSeries(seriesList);
                                        resp.setChartData(chartData);
                                        return resp;
                                    })
                            );

                    })
                    .collectList();
            });
    }

    public Mono<DataAnalysisDashboardChartsDetail> detail(String id){
        // 查询主表
        Mono<DataAnalysisDashboardChartsEntity> chartMono = super.createQuery()
            .where(DataAnalysisDashboardChartsEntity::getId, id)
            .fetchOne();

        // 查询XGroup
        Mono<List<DataAnalysisDashboardChartsXGroupEntity>> xGroupMono = dataAnalysisDashboardChartsXGroupService.createQuery()
            .where(DataAnalysisDashboardChartsXGroupEntity::getChartId, id)
            .fetch()
            .collectList();

        // 查询FilterCondition
        Mono<List<DataAnalysisDashboardChartsFilterConditionEntity>> filterMono = dataAnalysisDashboardChartsFilterConditionService.createQuery()
            .where(DataAnalysisDashboardChartsFilterConditionEntity::getChartId, id)
            .fetch()
            .collectList();

        // 组装
        return Mono.zip(chartMono, xGroupMono, filterMono)
            .map(tuple -> {
                DataAnalysisDashboardChartsDetail detail = new DataAnalysisDashboardChartsDetail();
                detail.setChart(tuple.getT1());
                detail.setXGroups(tuple.getT2());
                detail.setFilterConditions(tuple.getT3());
                return detail;
            });
    }
}
